﻿using System;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;

public class AtlasHierarchy : MonoBehaviour
{
    public AtlasData atlas;
}

// ------------------------------------------------------------------------------------------------
[System.Serializable]
public class AtlasData
{
    [System.Serializable]
    public class SpriteData
    {
        public Sprite sprite;   // 精灵
        public Vector4 padding; // 白边
        public bool trim;       // 是否切白边

        public SpriteData(Sprite s)
        {
            sprite = s;
        }

        public SpriteData(Sprite s, Vector4 p, bool t = false)
        {
            sprite = s;
            padding = p;
            trim = t;
        }

        public void SetSprite(Sprite s, Vector4 p, bool t = false)
        {
            sprite = s;
            padding = p;
            trim = t;
        }

        public string name
        {
            get
            {
                if (sprite != null)
                {
                    return sprite.name;
                }
                else
                {
                    return "";
                }
            }
        }
    }

    public Material material;                   // 材质
    public List<SpriteData> sprites;            // Sprite列表

    Dictionary<string, SpriteData> spriteMap;   // Sprite列表

    public void InitMap()
    {
        if (spriteMap != null)
        {
            // 已经初始化过了
            return;
        }

        spriteMap = new Dictionary<string, SpriteData>();
        if (sprites != null)
        {
            SpriteData data = null;
            for (int i = 0; i < sprites.Count; ++i)
            {
                data = sprites[i];
                spriteMap.Add(data.name, data);
            }
        }
    }

    public void Dispose()
    {
        spriteMap = null;
    }

    public int SpriteCount
    {
        get
        {
            InitMap();
            return spriteMap.Count;
        }
    }

    public string[] SpriteNames
    {
        get
        {
            InitMap();

            string[] names = new string[spriteMap.Count];
            spriteMap.Keys.CopyTo(names, 0);
            return names;
        }
    }

    int _referenceCount;
    public int ReferenceCount
    {
        get
        {
            return _referenceCount;
        }
        set
        {
            _referenceCount = value;
        }
    }

    public string Name  // 图集名字
    {
        get; set;
    }

    // 添加一个Sprite
    public void AddSprites(Sprite[] sprites)
    {
        for (int i = 0; i < sprites.Length; ++i)
        {
            AddSprite(sprites[i]);
        }
    }

    // 添加一个Sprite
    public void AddSprite(Sprite sprite)
    {
        InitMap();

        if (!spriteMap.ContainsKey(sprite.name))
        {
            // 不存在,添加
            spriteMap.Add(sprite.name, new SpriteData(sprite, Vector4.zero));
        }
        else
        {
            // 已经存在,替换
            spriteMap[sprite.name].SetSprite(sprite, Vector4.zero);
        }
    }

    public void RemoveSprites(Sprite[] sprites)
    {
        Sprite sprite = null;
        for (int i = 0; i < sprites.Length; ++i)
        {
            sprite = sprites[i];
            if (spriteMap.ContainsKey(sprite.name))
            {
                spriteMap.Remove(sprite.name);
            }
        }
    }

    SpriteData GetSpriteData(string name)
    {
        InitMap();

        SpriteData data = null;
        spriteMap.TryGetValue(name, out data);

        return data;
    }

    // 根据名称查找Sprite
    public Sprite GetSprite(string name)
    {
        SpriteData data = GetSpriteData(name);
        if (data == null)
        {
            return null;
        }

        ++ReferenceCount;
        return data.sprite;
    }

    // 根据名称查找SpriteInfo
    public SpriteInfo GetSpriteInfo(string name)
    {
        SpriteData data = GetSpriteData(name);
        if (data == null)
        {
            return null;
        }

        SpriteInfo info = new SpriteInfo();
        info.sprite = data.sprite;
        info.padding = data.padding;
        info.trim = data.trim;
        info.ad = this;

        //++ReferenceCount;
        return info;
    }

    // 查找并设置给Image(包括Sprite和材质)
    public void SetToImage(SDImage image, string name)
    {
        SpriteData data = GetSpriteData(name);
        if (data != null)
        {
            SetImage(image, this, data.sprite, data.trim);
        }
        else
        {
            image.sprite = null;
            image.material = null;
        }
    }

    public static void SetImage(SDImage image, AtlasData ad, Sprite sprite, bool trim)
    {
        image.sprite = sprite;
        image.SpriteName = sprite.name;
        if (ad.material != null || !(image.material != null && string.Equals(image.material.shader.name, "UI/Default(grey)")))
        {
            image.material = ad.material;
        }
        else
        {
            image.material = null;
        }

        AtlasReference reference = image.GetAtlasReference();
        if (reference != null)
            reference.AddRef(image, ad);
    }
}

// ------------------------------------------------------------------------------------------------
public class SpriteInfo
{
    public Sprite sprite;       // sprite
    public bool trim;           // 是否是去白边
    public Vector4 padding;     // 白边
    public AtlasData ad;

    // 查找并设置给Image(包括Sprite和材质)
    public void SetToImage(SDImage image)
    {
        AtlasData.SetImage(image, ad, sprite, trim);
    }
}

public static class ImageExtensions
{
    public static void SetSpriteName(this SDImage img, string spriteName)
    {
        string atlasName = SpriteAssetManager.Instance.GetAtlasName(spriteName);
        SpriteInfo spriteInfo = GetSpriteInfo(atlasName, spriteName);
        spriteInfo.SetToImage(img);
    }
    //不报错方法，有额外性能消耗，只用在作弊界面
    public static void SetSpriteNameSafe(this SDImage img, string spriteName)
    {
        string atlasName = SpriteAssetManager.Instance.GetAtlasName(spriteName);
        if (!string.IsNullOrEmpty(atlasName))
        {
            SpriteInfo spriteInfo = GetSpriteInfo(atlasName, spriteName);
            if (spriteInfo != null)
            {
                spriteInfo.SetToImage(img);
            }
        }
    }
    public static void SetSpriteName(this Button btn, string spriteName)
    {
        SDImage img = btn.GetComponent<SDImage>();
        if (img != null)
        {
            string atlasName = SpriteAssetManager.Instance.GetAtlasName(spriteName);
            SpriteInfo spriteInfo = GetSpriteInfo(atlasName, spriteName);
            spriteInfo.SetToImage(img);
        }
    }

    public static void SetEffectSpriteName(this SDEffectSprite img, string spriteName)
    {
        string atlasName = SpriteAssetManager.Instance.GetAtlasName(spriteName);
        SpriteInfo spriteInfo = GetSpriteInfo(atlasName, spriteName);
        img.sprite = spriteInfo.sprite;
    }

    public static SpriteInfo GetSpriteInfo(string atlasName, string spriteName)
    {
        SpriteInfo spriteInfo = null;
        LoadManager.Instance.LoadSprite(atlasName, spriteName, (data) =>
        {
            spriteInfo = data as SpriteInfo;
        }, false, true, true);
        return spriteInfo;
    }

    public static void SetSpriteInfo(this SDImage image, SpriteInfo data)
    {
        data.SetToImage(image);
    }

    // 扩展一个SetSprite方法(image.SetSprite(data))
    public static void SetSprite(this SDImage image, Sprite data)
    {
        image.sprite = data;
        image.material = null;
        image.SpriteName = string.Empty;
    }

    public static void SetUrlSprite(this SDImage image, Sprite data)
    {
        image.m_IsUrl = true;
        if (image.gameObject)
        {
            image.SetSprite(data);
        }
    }

    public static void SetImageColor(this Button btn, Color color)
    {
        SDImage img = btn.GetComponent<SDImage>();
        if (img != null)
        {
            img.color = color;
        }
    }
    public static void SetImageColor(this SDImage image, Color color)
    {
        if (image != null)
        {
            image.color = color;
        }
    }

    public static void SetImageRaycastTarget(this Button btn, bool raycastTarget)
    {
        SDImage img = btn.GetComponent<SDImage>();
        if (img != null)
        {
            img.raycastTarget = raycastTarget;
        }
    }
}